#include <iostream>
#include <string.h>

using namespace std;

class String
{
private:
    char *m_data;
public:
    String();
    String(const char * str);
    String(const String &rhs);
    virtual ~String();
    String& operator = (const String &rhs);

    void Print();
};

String::String() : m_data(NULL)
{
    cout << __FUNCTION__ << " " << __LINE__ << " " << __FILE__ << endl;
}

String::String(const char * str)
{
    if (str == NULL) {
        m_data = new char[1];
        m_data[0] = 0;
    } else {
        m_data = new char[strlen(str) + 1];
        strcpy(m_data, str);
    }
    cout << __FUNCTION__ << " " << __LINE__ << " " << __FILE__ << endl;    
    cout << "String::String(const char *str)" << endl;
}

String::String(const String &rhs)
{
    m_data = new char[strlen(rhs.m_data) + 1];
    strcpy(m_data, rhs.m_data);

    cout << __FUNCTION__ << " " << __LINE__ << " " << __FILE__ << endl;
    cout << "String::String(const &rhs)" << endl;
}

String::~String()
{
    if (m_data) {
        delete[] m_data;
    }

    cout << __FUNCTION__ << " " << __LINE__ << " " << __FILE__ << endl;
    cout << "String::~String" << endl;
}

String& String::operator = (const String &rhs)
{
    if (this == &rhs) {
        return *this;
    }
    
    if (m_data) {
        delete[] m_data;        
    }

    m_data = new char[strlen(rhs.m_data) + 1];
    strcpy(m_data, rhs.m_data);

    cout << __FUNCTION__ << " " << __LINE__ << " " << __FILE__ << endl;
    cout << "String::operator=" << endl;
}

void String::Print()
{
    if (m_data) {
        cout << "Content: " << this->m_data << endl;
    }
}

int main(int argc, char *argv[])
{
    String myString1("hello");
    String myString2(myString1);
    String myString3;

    cout << "sizeof(String) = " << sizeof(String) << endl;

    myString1.Print();
    myString2.Print();
    myString3.Print();

    cout << "run operator = " << endl;
    
    myString3 = myString2;
    myString3.Print();

    cout << "alloc array" << endl;
    String *pstrs = new String[3];
    cout << "alloc array success" << endl;
    delete[] pstrs;
    cout << "delete array success" << endl;
    
    return 0;
}
